跳到主要内容

关于 for...in

for...in

for...in 语句以任意顺序迭代一个对象的除 Symbol 以外的可枚举属性,包括继承的可枚举属性。

Note

for in 不应该用于迭代一个关注索引顺序的 Array,因为它会把索引顺序的错误暴露给用户。

另外,for in 也不建议用于迭代数组。

定义一个 animalrabbit 对象,rabbit 原型为 animal 。

let animal = {
eats: true,
}

let rabbit = {
jumps: true,
__proto__: animal,
}

for...in迭代继承的属性

for (let i in rabbit) {
console.log(i)
}
//jumps eats

怎么才能遍历 rabbit 自己的属性?

1. 使用 Object.keys(obj)

仅返回 rabbit 对象自己的可枚举属性。

Object.keys(rabbit)

这些属性的顺序与手动遍历该对象属性时的一致。

2. 使用 obj.hasOwnProperty(key) 过滤

for (let i in rabbit) {
if (rabbit.hasOwnProperty(i)) {
console.log(i)
}
}
// jumps

3. getOwnPropertyNames

for (let i in rabbit) {
console.log(Object.getOwnPropertyNames(rabbit))
}
// [ 'jumps']

但这样会把不可枚举对象也返回

例如:

下边的代码定义了一个对象 o,属性 aenumerable 的,b 不是。

// 创建一个新对象
var o = { a: 'cat' }

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, 'b', {
value: 'dog',
writable: true,
enumerable: false,
configurable: true,
})

如果现在还要使用 Object.getOwnPropertyNames(obj),就会把不可枚举的属性也返回。

console.log(Object.getOwnPropertyNames(o))
// [ 'a', 'b' ]
// 这里的 b 是不可枚举的。

再比如:

const arr = ['a', 'b', 'c']
console.log(Object.getOwnPropertyNames(arr))
//['0', '1', '2', 'length']
// 这里的 length 是不可枚举的。

通常我们并不需要返回那些不可枚举的属性,

所以可以使用 Object.prototype.propertyIsEnumerable(prop) 过滤掉不可枚举的属性。

Note

可能你会发现,既然 for...in 会迭代继承的属性, 那为什么 Object.prototype 的属性却没有被遍历呢?

这是因为 Object.prototype 中的属性有 enumerable:false 的标志。

  基本包装类型的原型属性是不可枚举的

最后,for...in 是为遍历对象属性而构建的,不建议与数组一起使用。

如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用 propertyIsEnumerable)。

for...of

for...of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

对于 for...of 的循环,可以由 break, throw 或 return 终止。

for...infor...of 的区别

它们之间的主要区别在于它们的迭代方式

for...in 为了遍历一个对象的所有键(key),语句以任意顺序迭代对象的可枚举属性

for...of 语句遍历可迭代对象定义要迭代的数据

并且,不建议使用 for...in 遍历数组。

👇 如果你有好的想法,请一起完善吧